package com.un.ebs.production.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.contract.domain.ContractItemExt;
import com.un.ebs.contract.dto.ContractDto;
import com.un.ebs.contract.dto.ContractItemDto;
import com.un.ebs.contract.service.ContractService;
import com.un.ebs.core.enums.BooleanEnum;
import com.un.ebs.core.exception.BusinessEntityNotFoundException;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.util.DateUtils;
import com.un.ebs.core.util.SecurityUtils;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.data.conditions.Wrapper;
import com.un.ebs.inventory.domain.InventoryNote;
import com.un.ebs.inventory.domain.InventoryNoteItem;
import com.un.ebs.inventory.domain.InventoryNoteItemExt;
import com.un.ebs.inventory.dto.InventoryNoteAddDto;
import com.un.ebs.inventory.dto.InventoryNoteItemDto;
import com.un.ebs.inventory.dto.InventoryNoteVo;
import com.un.ebs.inventory.enums.InventoryTypeEnum;
import com.un.ebs.inventory.mapper.InventoryNoteItemMapper;
import com.un.ebs.inventory.mapper.InventoryNoteMapper;
import com.un.ebs.inventory.service.InventoryNoteService;
import com.un.ebs.inventory.service.InventoryNoteTypeService;
import com.un.ebs.product.domain.ProductSkuExt;
import com.un.ebs.product.dto.ProductSkuVo;
import com.un.ebs.product.enums.ProductPurchaseTypeEnum;
import com.un.ebs.product.service.ProductSkuService;
import com.un.ebs.production.domain.*;
import com.un.ebs.production.dto.*;
import com.un.ebs.production.mapper.*;
import com.un.ebs.production.service.ProductionOrderService;
import com.un.ebs.production.service.ProductionSeqService;
import com.un.ebs.purchase.domain.PurchaseOrder;
import com.un.ebs.purchase.domain.PurchaseOrderItem;
import com.un.ebs.purchase.domain.PurchaseOrderItemExt;
import com.un.ebs.purchase.dto.PurchaseItemCreateDto;
import com.un.ebs.purchase.dto.PurchaseOrderItemDto;
import com.un.ebs.purchase.dto.PurchaseOrderUpdateDto;
import com.un.ebs.purchase.mapper.PurchaseOrderItemExtMapper;
import com.un.ebs.purchase.mapper.PurchaseOrderMapper;
import com.un.ebs.purchase.service.PurchaseOrderService;
import com.un.ebs.quality.domain.QualityCheck;
import com.un.ebs.sale.domain.SaleOrder;
import com.un.ebs.sale.domain.SaleOrderDeliverPlanExt;
import com.un.ebs.sale.domain.SaleOrderItemExt;
import com.un.ebs.sale.dto.SaleOrderVo;
import com.un.ebs.sale.service.SaleOrderService;
import com.un.ebs.sys.domain.Personnel;
import com.un.ebs.sys.service.PersonnelService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liubo
 * @since 2020-05-25
 */
@Service
public class ProductionOrderServiceImpl extends ServiceImpl<ProductionOrderMapper, ProductionOrder> implements ProductionOrderService {

    @Resource
    private PersonnelService personnelService;

    @Resource
    private ProductSkuService productSkuService;

    @Resource
    private InventoryNoteItemMapper inventoryNoteItemMapper;

    @Resource
    private InventoryNoteMapper inventoryNoteMapper;

    @Resource
    private ContractService contractService;

    @Resource
    private PurchaseOrderMapper purchaseOrderMapper;

    @Resource
    private PurchaseOrderItemExtMapper purchaseOrderItemExtMapper;

    @Resource
    private InventoryNoteService inventoryNoteService;

    @Resource
    private ProductionSeqService productionSeqService;

    @Resource
    private ProductionOrderItemMapper productionOrderItemMapper;

    @Resource
    private ProductionOrderItemExtMapper productionOrderItemExtMapper;

    @Resource
    private ProductionWorkOrderOutExtMapper productionWorkOrderOutExtMapper;

    @Resource
    private ProductionOrderViewMapper productionOrderViewMapper;

    @Resource
    private ProductionRequirementPlanExtMapper productionRequirementPlanExtMapper;

    @Resource
    private ProductionOrderItemBomSumExtMapper productionOrderItemBomSumExtMapper;

    @Resource
    private ProductionOrderItemBomExtMapper productionOrderItemBomExtMapper;

    @Resource
    private ProductionOrderExtMapper productionOrderExtMapper;

    @Resource
    private InventoryNoteTypeService inventoryNoteTypeService;

    @Resource
    private PurchaseOrderService purchaseOrderService;

    @Resource
    private SaleOrderService saleOrderService;

    @Resource
    private ProductionWorkOrderMapper productionWorkOrderMapper;

    @Resource
    private ProductionOrderRequirementPlanExtMapper productionOrderRequirementPlanExtMapper;

    @Resource
    private ProductionCostDiffExtMapper productionCostDiffExtMapper;

    @Transactional
    @Override
    public String add(ProductionOrderAddDto req) {
        ProductionOrderUpdateDto obj = new ProductionOrderUpdateDto();
        BeanUtils.copyProperties(req, obj);
        return save(obj, false, false).getId();
    }

    @Transactional
    @Override
    public String addReBuild(ProductionOrderRebuildDto req) {
        ProductionOrderUpdateDto obj = new ProductionOrderUpdateDto();
        obj.setBomType(req.getBomType());
        obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        obj.setPlanDeliverDate(req.getPlanDeliverDate());
        obj.setPlanWorkDate(req.getPlanWorkDate());
        obj.setRemark(req.getRemark());

        ProductionOrderItemDto item = new ProductionOrderItemDto();
        item.setSkuId(req.getSkuId());
        item.setQty(req.getQty());
        List<ProductionOrderItemDto> items = new ArrayList<>();
        items.add(item);
        obj.setItems(items);

        ProductionOrder productionOrder = save(obj, true, true);

        InventoryNoteAddDto outNote = new InventoryNoteAddDto();
        outNote.setWarehouseId(req.getWarehouseId());
        outNote.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        outNote.setNoteType(InventoryTypeEnum.PRODUCTION_BOM_USER);
        outNote.setRelationNoteCode(productionOrder.getCode());
        outNote.setRelationNoteId(productionOrder.getId());
        outNote.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION).getId());
        outNote.setSubmitStatus(true);
        outNote.setRemark(req.getRemark());
        outNote.setIsRebuild(true);

        List<InventoryNoteItemDto> noteItems = new ArrayList<>();
        InventoryNoteItemDto noteItem = new InventoryNoteItemDto();
        noteItem.setSkuId(req.getSkuId());
        noteItem.setQty(req.getQty());
        noteItems.add(noteItem);
        outNote.setItems(noteItems);
        inventoryNoteService.addByOut(outNote);

        return productionOrder.getId();

    }

    private void checkSaleOrderDeliverPlan(SaleOrderVo order, String skuCode) {
        if (!order.getSubmitStatus()) {
            throw new BusinessException("销售订单未提交。");
        }
        StringBuilder sb = new StringBuilder();
        for (SaleOrderItemExt item : order.getItems().stream().filter(s -> s.getSkuCode().equals(skuCode)).collect(Collectors.toList())) {
            List<SaleOrderDeliverPlanExt> list = saleOrderService.queryDeliverPlan(skuCode);
            Double reqQty = list.stream().mapToDouble(s -> s.getProductionRequirementQty()).sum();
            if (reqQty <= 0) {
                double historyQty = Math.abs(list.stream().filter(s -> s.getProductionRequirementQty() < 0).mapToDouble(s -> s.getProductionRequirementQty()).sum());
                throw new BusinessException(String.format("【%s，%s】历史订单有变更，存在超销售订单下达生产计划【%s】，因此，当前不再需要再创建生产订单。", item.getSkuCode(), item.getNameAs(), historyQty));
            }
        }
    }

    @Override
    public String add(ProductionOrderAddBySaleDto req) {
        SaleOrderVo saleOrder = saleOrderService.queryViewById(req.getSaleOrderId());
        if (saleOrder == null) {
            throw new BusinessEntityNotFoundException(req.getSaleOrderId(), "销售订单");
        }
        if (!saleOrder.getSubmitStatus()) {
            throw new BusinessException("销售订单未提交。");
        }
        if (saleOrder.getSumQty() <= saleOrder.getDeliverQty()) {
            throw new BusinessException("销售订单已完成交付，不能再创建生产订单。");
        }

        Optional<SaleOrderItemExt> item = saleOrder.getItems().stream().filter(s -> s.getId().equals(req.getSaleOrderItemId())).findFirst();
        if (!item.isPresent()) {
            throw new BusinessEntityNotFoundException(req.getSaleOrderItemId(), "销售订单明细");
        }
        if (item.get().getQty() <= item.get().getDeliverCount()) {
            throw new BusinessException(String.format("【%s : %s】 已完成交付，不能再创建生产订单", item.get().getSkuCode(), item.get().getNameAs()));
        }
        if ((item.get().getQty() - item.get().getDeliverCount()) < req.getQty()) {
            throw new BusinessException("当前计划生产量不能大于销售数量");
        }

        // 检查综合需求
        checkSaleOrderDeliverPlan(saleOrder, item.get().getSkuCode());

        ProductionOrderUpdateDto obj = new ProductionOrderUpdateDto();
        obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        obj.setSaleOrderId(req.getSaleOrderId());
        obj.setSaleOrderItemId(req.getSaleOrderItemId());
        obj.setRemark(item.get().getRemark());
        obj.setPlanWorkDate(req.getPlanStart());
        obj.setPlanDeliverDate(req.getPlanEnd());
        obj.setBomType(req.getBomType());

        List<ProductionOrderItemDto> itemDtos = new ArrayList<>();
        ProductionOrderItemDto objItem = new ProductionOrderItemDto();
        objItem.setSkuId(item.get().getSkuId());
        objItem.setQty(req.getQty());
        itemDtos.add(objItem);
        obj.setItems(itemDtos);

        return save(obj, true, false).getId();
    }

    @Transactional
    @Override
    public void update(ProductionOrderUpdateDto req) {
        save(req, false, false);
    }

    public ProductionOrder save(ProductionOrderUpdateDto req, boolean isSubmit, boolean isRebuild) {
        if (StringUtils.isNullOrEmpty(req.getItems())) {
            throw new BusinessException("订单明细不能为空。");
        }
        ProductionOrder obj = null;
        if (!StringUtils.isNullOrEmpty(req.getId())) {
            obj = getById(req.getId());
            if (obj.getSubmitStatus()) {
                throw new BusinessException("订单已提交，不能修改。");
            }
        } else {
            obj = new ProductionOrder();
            obj.setCode(String.format("MO-%s%04d", DateUtils.formatDate(new Date(), "yyyyMM"), baseMapper.maxCode() + 1));
        }
        obj.setSaleOrderId(req.getSaleOrderId());
        obj.setBomType(req.getBomType());
        obj.setPlanWorkDate(req.getPlanWorkDate());
        obj.setPlanDeliverDate(req.getPlanDeliverDate());
        obj.setIsRebuild(isRebuild);

        if (StringUtils.isNullOrEmpty(req.getPersonnelId())) {
            obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
            obj.setPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        } else {
            Personnel personnel = personnelService.queryById(req.getPersonnelId());
            if (personnel == null) {
                throw new BusinessEntityNotFoundException(req.getPersonnelId(), "员工");
            }
            obj.setPersonnelId(personnel.getId());
            obj.setPersonnelName(personnel.getName());
        }

        if (isSubmit) {
            obj.setSubmitStatus(true);
            obj.setSubmitAt(SecurityUtils.getUserContent().getId());
            obj.setSubmitAtName(SecurityUtils.getUserContent().getPersonnelName());
            obj.setSubmitTime(new Date());
        }

        obj.insertOrUpdate();

        // 清除订单明细
        LambdaQueryWrapper<ProductionOrderItem> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItem::getOrderId, obj.getId());
        productionOrderItemMapper.delete(lq);

        for (ProductionOrderItemDto item : req.getItems()) {
            if (item.getQty() <= 0) {
                throw new BusinessException("数量不能为0。");
            }
            ProductionOrderItem objItem = new ProductionOrderItem();
            objItem.setId(item.getId());
            objItem.setSkuId(item.getSkuId());
            objItem.setOrderId(obj.getId());
            objItem.setSaleOrderItemId(req.getSaleOrderItemId());
            objItem.setQty(item.getQty());
            //objItem.setProductionSeqId();

            if (isSubmit) {
                int index = baseMapper.selectMaxSerialNo(SecurityUtils.getTenantId());
                objItem.setSerialNoBegin(index + 1);
                objItem.setSerialNoEnd(index + item.getQty().intValue());
            }

            objItem.insertOrUpdate();
        }

        return obj;
    }

    @Override
    public void delete(String id) {
        ProductionOrder obj = getById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "生产订单");
        }
        if (obj.getSubmitStatus()) {
            throw new BusinessException("单据已提交，不能执行此操作。");
        }
        getBaseMapper().deleteById(id);
    }

    @Override
    public void submit(String id) {
        ProductionOrder obj = getById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "生产订单");
        }
        if (obj.getSubmitStatus()) {
            throw new BusinessException("不能重复提交。");
        }
        if (!SecurityUtils.getUserContent().getId().equals(obj.getCreateAt())) {
            throw new BusinessException("此操作只能由创建人完成。");
        }

        obj.setSubmitStatus(true);
        obj.setSubmitAt(SecurityUtils.getUserContent().getId());
        obj.setSubmitAtName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setSubmitTime(new Date());
        obj.updateById();

        int index = baseMapper.selectMaxSerialNo(obj.getTenantId());

        for (ProductionOrderItem item : queryItemById(id)) {
            if (item.getSerialNoBegin() != 0) {
                continue;
            }
            item.setSerialNoBegin(index + 1);
            item.setSerialNoEnd(index + item.getQty().intValue());
            item.updateById();
        }
    }

    @Transactional
    @Override
    public void submitCancel(String id) {
        ProductionOrder obj = baseMapper.selectById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "生产订单");
        }
        if (!obj.getSubmitStatus()) {
            throw new BusinessException("生产订单未审批，无需撤销。");
        }
        if (obj.getPlanWorkStatus()) {
            throw new BusinessException("生产订单已开工，不能撤销。");
        }
        if (obj.getIsRebuild()) {
            //检查相应的出库单
            InventoryNoteVo note = inventoryNoteService.queryRebuildNoteByRelation(obj.getId());
            if (note != null) {
                if (note.getAuditStatus()) {
                    throw new BusinessException("返工再造产品的领料单已审核，请先撤销审核后再执行此操作。");
                }
                if (note.getSubmitStatus()) {
                    inventoryNoteService.submitCancel(note.getId(), false);
                }
                //inventoryNoteService.delete(note.getId());
            }
        }

        obj.setSubmitStatus(false);
        obj.setSubmitTime(null);
        obj.setSubmitAt(null);
        obj.setSubmitAtName(null);
        obj.updateById();
        obj.deleteById();

    }

    @Transactional
    @Override
    public void run(String id, String seqId) {
        ProductionOrder obj = queryById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "生产订单");
        }
        if (!obj.getSubmitStatus()) {
            throw new BusinessException("订单没有提交。");
        }
        if (obj.getPlanWorkStatus()) {
            throw new BusinessException("生产订单不能重复安排计划。");
        }
        if (obj.getPlanWorkDate() == null) {
            obj.setPlanWorkDate(new Date());
        } //else {
//            if (new Date().getTime() >= obj.getPlanWorkDate().getTime()) {
//                throw new BusinessException("计划开工日期必须是未来时间。");
//            }
//        }
        if (!obj.getIsRebuild()) {
            runBomInventoryCheck(id);
        }

        List<ProductionOrderItem> items = queryItemById(id);
        if (items.size() != 1) {
            throw new BusinessException("一笔生产订单只能有一个产品数据。");
        }

        SaleOrder saleOrder = saleOrderService.queryById(obj.getSaleOrderId());
        if (saleOrder == null && obj.getIsRebuild() == false) {
            throw new BusinessEntityNotFoundException(obj.getSaleOrderId(), "销售订单");
        }

        for (ProductionOrderItem item : items) {
            ProductSkuExt sku = productSkuService.queryViewById(item.getSkuId());
            if (sku == null) {
                throw new BusinessEntityNotFoundException(item.getSkuId(), "SKU");
            }
            if (sku.getPurchaseType() != ProductPurchaseTypeEnum.Produce) {
                throw new BusinessException(String.format("当前所需生产的产品属性【采购类别】不是 %s ，请确认。", sku.getPurchaseType().getDesc()));
            }

            //String seqId = StringUtils.isNullOrEmpty(item.getProductionSeqId()) ? sku.getProductionSeqId() : item.getProductionSeqId();
            if (StringUtils.isNullOrEmpty(seqId)) {
                seqId = sku.getProductionSeqId();
            }
            if (StringUtils.isNullOrEmpty(seqId)) {
                throw new BusinessException(String.format("产品【%s : %s】没有定义工序集，请指定工序集后再执行此操作。", sku.getSkuCode(), sku.getName()));
            }
            item.setProductionSeqId(seqId);
            item.updateById();

            if (sku.getItemCount() == 0) {
                throw new BusinessException("当前所需生产的产品没有定义物料清单。");
            }
            if (productSkuService.queryItemBySkuId(item.getSkuId()).stream().filter(s -> s.getBomType().equals(obj.getBomType()) && s.getIsDelete() == false).count() == 0) {
                throw new BusinessException(String.format("【%s】没有定义【%s】。", sku.getSkuCode(), obj.getBomType().getDesc()));
            }
            if (sku.getPurchaseType() != ProductPurchaseTypeEnum.Produce) {
                throw new BusinessException("当前所需生产的的【采购类型】不是【内部生产】，请确认后再继续。");
            }

            // 生成工单
            for (ProductionSeqItemExt seqItem : productionSeqService.queryItemView(seqId, -1, 1).getRecords()) {
                ProductionWorkOrder workOrder = new ProductionWorkOrder();
                workOrder.setProductionOrderItemId(item.getId());
                workOrder.setProductionSeqItemId(seqItem.getId());
                workOrder.setPlanWorkQty(item.getQty());
                workOrder.setPlanWorkDate(obj.getPlanWorkDate());
                workOrder.setRealStartTime(new Date());
                workOrder.insert();

                if (seqItem.getPurchaseType() == ProductPurchaseTypeEnum.Purchase) {
                    //生成服务性采购
                    if (!StringUtils.isNullOrEmpty(seqItem.getRelationSkuId())) {
                        if (seqItem.getRelationUserQty() <= 0) {
                            throw new BusinessException("委外服务数量不能为1");
                        }

                        purchaseOrderService.addByService(id, item.getId(), seqItem.getId());
                    } else {
                        throw new BusinessException("委外工序未指定关联的物料，请添加工序关联物料或将工序调整为【内部生产】。");
                    }
                }
            }
        }

        obj.setPlanWorkStatus(true);
        obj.setPlanWorkPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        obj.setPlanWorkPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setRealWorkDate(new Date());
        obj.updateById();
    }

    @Override
    public void runFix(String code) {
        ProductionOrderView order = queryViewByCode(code);
        if (order == null) {
            throw new BusinessEntityNotFoundException(code, "生产订单");
        }
        if (!order.getPlanWorkStatus()) {
            throw new BusinessException("此操作只针对已开工的生产订单。");
        }

        if (order.getPurchaseType() != ProductPurchaseTypeEnum.Produce) {
            throw new BusinessException(String.format("当前所需生产的产品属性【采购类别】不是 %s ，请确认。", order.getPurchaseType().getDesc()));
        }
        if (StringUtils.isNullOrEmpty(order.getProductionSeqId())) {
            throw new BusinessException(String.format("产品【%s : %s】没有定义工序集，请指定工序集后再执行此操作。", order.getSkuCode(), order.getSkuName()));
        }
        if (productionWorkOrderMapper.selectByItemId(order.getId()).size() > 0) {
            throw new BusinessException(String.format("%s 已生成了工序，不能重复生成。", order.getCode()));
        }

        // 生成工单
        for (ProductionSeqItemExt seqItem : productionSeqService.queryItemView(order.getProductionSeqId(), -1, 1).getRecords()) {
            ProductionWorkOrder workOrder = new ProductionWorkOrder();
            workOrder.setProductionOrderItemId(order.getId());
            workOrder.setProductionSeqItemId(seqItem.getId());
            workOrder.setPlanWorkQty(order.getProductionQty());
            workOrder.setPlanWorkDate(order.getPlanWorkDate());
            workOrder.setRealStartTime(new Date());
            workOrder.insert();

            if (seqItem.getPurchaseType() == ProductPurchaseTypeEnum.Purchase) {
                //生成服务性采购
                if (!StringUtils.isNullOrEmpty(seqItem.getRelationSkuId())) {
                    purchaseOrderService.addByService(order.getOrderId(), order.getId(), seqItem.getId());
                } else {
                    throw new BusinessException("委外工序未指定关联的物料，请添加工序关联物料或将工序调整为【内部生产】。");
                }
            }
        }
    }

    @Override
    public String runServicePurchaseFix(String code) {
        ProductionOrderView order = queryViewByCode(code);
        if (order == null) {
            throw new BusinessEntityNotFoundException(code, "生产订单");
        }
        if (!order.getPlanWorkStatus()) {
            throw new BusinessException("此操作只针对已开工的生产订单。");
        }
        if (order.getPurchaseType() != ProductPurchaseTypeEnum.Produce) {
            throw new BusinessException(String.format("当前所需生产的产品属性【采购类别】不是 %s ，请确认。", order.getPurchaseType().getDesc()));
        }
        if (StringUtils.isNullOrEmpty(order.getProductionSeqId())) {
            throw new BusinessException(String.format("产品【%s : %s】没有定义工序集，请指定工序集后再执行此操作。", order.getSkuCode(), order.getSkuName()));
        }

        //查询当前生产订单的服务采购订单
        LambdaQueryWrapper<PurchaseOrder> purchaseQuery = Wrappers.lambdaQuery();
        purchaseQuery.eq(PurchaseOrder::getProductionOrderId, order.getOrderId());
        purchaseQuery.eq(PurchaseOrder::getIsServices, true);
        purchaseQuery.eq(PurchaseOrder::getIsDelete, false);
        List<PurchaseOrder> purchaseOrders = purchaseOrderMapper.selectList(purchaseQuery);

        List<ProductionWorkOrderExt> list = productionWorkOrderMapper.selectByItemId(order.getId());
        StringBuilder msg = new StringBuilder();
        for (ProductionWorkOrderExt work : list) {
            if (work.getSeqItemPurchaseType() == ProductPurchaseTypeEnum.Purchase || !StringUtils.isNullOrEmpty(work.getRelationSkuId())) {
                Double planQty = work.getPlanWorkQty() * work.getProductionSeqQty();
                List<PurchaseOrderItemExt> purchaseList = purchaseOrderService.queryItemByProductionOrder(work.getProductionOrderId()).stream().filter(s -> s.getSkuId().equals(work.getRelationSkuId())).collect(Collectors.toList());

                //未生成，自动修改
                if (StringUtils.isNullOrEmpty(purchaseList)) {
                    // 加到现有服务采购订单中
                    List<ContractItemExt> contractItems = contractService.queryPurchasePriceList(work.getRelationSkuId());
                    if (StringUtils.isNullOrEmpty(contractItems)) {
                        msg.append("修复采购订单时，Sku 缺少有效的价格协议。");
                        continue;
                    }

                    List<String> hasEntIds = contractItems.stream().map(s -> s.getBusinessEntId()).collect(Collectors.toList());
                    Optional<PurchaseOrder> p = purchaseOrders.stream().filter(s -> hasEntIds.contains(s.getSupplierEntId())).findFirst();
                    if (p.isPresent()) {
                        PurchaseOrderItem item = new PurchaseOrderItem();
                        item.setOrderId(p.get().getId());
                        item.setSkuId(work.getRelationSkuId());
                        item.setQty(planQty);
                        item.setPrice(contractItems.get(0).getPrice());
                        item.setProductionOrderItemId(work.getProductionOrderItemId());
                        item.insert();
                        msg.append(String.format("委外工序【%s：%s】的采购订单项未生成，已添加到采购订单【%s】。", work.getProductionSeqItemCode(), work.getProductionSeqItemName(), p.get().getCode()));
                        continue;
                    } else {
                        purchaseOrderService.addByService(work.getProductionOrderId(), work.getProductionOrderItemId(), work.getProductionSeqItemId());
                        continue;
                    }
                }

                if (purchaseList.size() > 1) {
                    msg.append(String.format("委外工序【%s：%s】的采购订单明细存在多笔相同的数据。", work.getProductionSeqItemCode(), work.getProductionSeqItemName()));
                }
                Double purchaseQty = purchaseList.stream().mapToDouble(s -> s.getQty()).sum();
                if (purchaseQty == null) {
                    msg.append(String.format("委外工序未生成采购：%s", work.getProductionOrderItemId()));
                    continue;
                }
                if (!planQty.equals(purchaseQty)) {
                    msg.append(String.format("委外工序【%s：%s】的计划采购数量【%s】与实际采购【%s】不符。产品编码为：%s", work.getProductionSeqItemCode(), work.getProductionSeqItemName(), planQty, purchaseQty, work.getRelationSkuId()));
                    continue;
                }
            }
        }
        return msg.toString();
    }

    @Transactional
    @Override
    public String runServicesNotAcceptFix(String code) {
        StringBuilder msg = new StringBuilder();
        ProductionOrderView order = queryViewByCode(code);
        if (order == null) {
            throw new BusinessEntityNotFoundException(code, "生产订单");
        }
        if (!order.getProductionQty().equals(order.getProductionInQty())) {
            throw new BusinessException("此操作只针对已开工的生产订单。");
        }
        if (order.getPurchaseType() != ProductPurchaseTypeEnum.Produce) {
            throw new BusinessException(String.format("当前所需生产的产品属性【采购类别】不是 %s ，请确认。", order.getPurchaseType().getDesc()));
        }
        if (StringUtils.isNullOrEmpty(order.getProductionSeqId())) {
            throw new BusinessException(String.format("产品【%s : %s】没有定义工序集，请指定工序集后再执行此操作。", order.getSkuCode(), order.getSkuName()));
        }

        //查询当前生产订单的服务采购订单
        LambdaQueryWrapper<PurchaseOrderItemExt> purchaseQuery = Wrappers.lambdaQuery();
        purchaseQuery.eq(PurchaseOrderItemExt::getProductionOrderId, order.getOrderId());
        purchaseQuery.eq(PurchaseOrderItemExt::getIsServices, true);
        purchaseQuery.eq(PurchaseOrderItemExt::getSubmitStatus, true);
        purchaseQuery.eq(PurchaseOrderItemExt::getIsDelete, false);
        List<PurchaseOrderItemExt> purchaseOrders = purchaseOrderItemExtMapper.selectList(purchaseQuery);

        for (PurchaseOrderItemExt item : purchaseOrders) {
            if (item.getQty().equals(item.getDeliverQty())) {
                continue;
            }

            // 正确下单，但没有收货的，恢复
            if (item.getDeliverQty() == 0) {
                Optional<InventoryNoteItemExt> noteItem = purchaseOrderItemExtMapper.queryPurchaseInNote(item.getOrderId()).stream().filter(s -> s.getIsDelete()).findFirst();
                if (noteItem.isPresent()) {
                    msg.append(String.format("采购入库已删除：%s", noteItem.get().getCode()));

                    InventoryNoteItem obj = inventoryNoteItemMapper.selectById(noteItem.get().getId());
                    obj.setSkuId(item.getSkuId());
                    obj.setPrice(item.getPrice());
                    obj.setQty(item.getQty());
                    obj.updateById();

                    InventoryNote note = inventoryNoteMapper.queryDeleteId(noteItem.get().getNoteId());
                    note.setSubmitStatus(true);
                    note.setAuditStatus(true);
                    note.updateById();

                    inventoryNoteMapper.recovery(noteItem.get().getNoteId());
                    msg.append("\r\n采购入库已修正。");

                    continue;
                }
            }


        }
        return msg.toString();

    }

    @Override
    public String runServicesOutFix(String code) {
        LambdaQueryWrapper<ProductionOrderItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItemExt::getCode, code);
        ProductionOrderItemExt note = productionOrderItemExtMapper.selectOne(lq);
        if (note == null) {
            throw new BusinessEntityNotFoundException(code, "生产订单");
        }

        if (note.getProductionDeliverQty() == 0) {
            throw new BusinessException("订单还未完工。");
        }

        // 查询领料情况
        List<InventoryTypeEnum> types = new ArrayList<>();
        types.add(InventoryTypeEnum.PRODUCTION_BOM_USER);
        types.add(InventoryTypeEnum.REPAIR_USER);
        List<InventoryNoteItemExt> items = inventoryNoteService.queryItemExtByRelationNoteId(note.getOrderId()).stream().filter(s -> types.contains(s)).collect(Collectors.toList());

        //查询所有应领物料
        LambdaQueryWrapper<ProductionOrderItemBomExt> query = Wrappers.lambdaQuery();
        query.eq(ProductionOrderItemBomExt::getOrderId, note.getOrderId());
        List<ProductionOrderItemBomExt> bomItems = productionOrderItemBomExtMapper.selectList(query);


        return null;
    }

    @Override
    public void runCancel(String id) {
        ProductionOrder obj = queryById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "生产订单");
        }
        if (!obj.getSubmitStatus()) {
            throw new BusinessException("订单没有提交。");
        }
        if (!obj.getPlanWorkStatus()) {
            throw new BusinessException("只有已开工的生产订单，才能撤销。");
        }

        List<InventoryNoteItemExt> outList = inventoryNoteService.queryItemExtByRelationNoteId(id);
        if (outList.stream().filter(s -> s.getSubmitStatus()).count() > 0 && obj.getIsRebuild() == false) {
            throw new BusinessException("已开始领料，请先撤销领料单【" + outList.get(0).getCode() + "】后，再执行此操作。");
        }
        List<PurchaseOrder> purchaseOrders = purchaseOrderService.queryByProductionOrder(id);
        if (purchaseOrders.size() > 0) {
            throw new BusinessException("当前生产订单【" + purchaseOrders.get(0).getCode() + "】已生成了采购订单，请先撤销采购订单后，再执行此操作。");
        }
        List<ProductionOrderItem> list = queryItemById(id);
        if (StringUtils.isNullOrEmpty(list)) {
            throw new BusinessException("订单明细为空。");
        }

        for (ProductionOrderItem item : list) {
            productionWorkOrderMapper.deleteQualityCheck(item.getId());

            LambdaQueryWrapper<ProductionWorkOrder> lq = Wrappers.lambdaQuery();
            lq.eq(ProductionWorkOrder::getProductionOrderItemId, item.getId());
            productionWorkOrderMapper.delete(lq);
        }

        obj.setPlanWorkStatus(false);
        obj.setPlanWorkDate(null);
        obj.setPlanWorkPersonnelId(null);
        obj.setPlanWorkPersonnelName(null);
        obj.setRealWorkDate(null);
        obj.updateById();
    }

    private void runBomInventoryCheck(String id) {
        LambdaQueryWrapper<ProductionOrderItemBomExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItemBomExt::getOrderId, id);
        List<ProductionOrderItemBomExt> list = productionOrderItemBomExtMapper.selectList(lq).stream().filter(s -> s.getIsAllowLackStart() == false).filter(s -> s.getRequirementQty() > s.getInventoryQty()).collect(Collectors.toList());
        for (ProductionOrderItemBomExt item : list) {
            throw new BusinessException(String.format("物料【%s】库存不足，缺件数量：%.2f %n，不允许开工。", item.getSkuCode(), item.getRequirementQty() - item.getInventoryQty()));
        }
    }

    @Override
    public void deliver(String id) {
        ProductionOrderView view = queryViewByOrderId(id);
        if (view == null) {
            throw new BusinessEntityNotFoundException(id, "生产订单");
        }
        if (view.getProductionQty().intValue() != view.getProductionInQty().intValue()) {
            return;
        }
        if (!view.getSubmitStatus()) {
            return;
        }
        if (view.getDeliverStatus()) {
            return;
        }

        ProductionOrder order = baseMapper.selectById(view.getOrderId());
        if (order == null) {
            throw new BusinessEntityNotFoundException(view.getOrderId(), "生产订单");
        }
        order.setDeliverAt(SecurityUtils.getUserContent().getId());
        order.setDeliverAtName(SecurityUtils.getUserContent().getPersonnelName());
        order.setDeliverTime(new Date());
        order.setDeliverStatus(true);
        order.updateById();
    }

    @Override
    public void productionToPurchaseOrder(List<PurchaseItemCreateDto> req) {
        List<PurchaseOrderUpdateDto> reqs = new ArrayList<>();
        for (String supplierId : req.stream().filter(s -> StringUtils.isNullOrEmpty(s.getProviderEntId()) == false).map(s -> s.getProviderEntId()).distinct().collect(Collectors.toList())) {

            PurchaseOrderUpdateDto order = new PurchaseOrderUpdateDto();
            List<PurchaseOrderItemDto> items = new ArrayList<>();
            for (PurchaseItemCreateDto item : req.stream().filter(s -> supplierId.equals(s.getProviderEntId())).collect(Collectors.toList())) {
                ProductSkuVo sku = productSkuService.queryViewById(item.getSkuId());

                if (sku.getPurchaseType() != ProductPurchaseTypeEnum.Purchase) {
                    throw new BusinessException("只有外部采购商品【" + sku.getSkuCode() + "】才能生成采购订单。");
                }
                PurchaseOrderItemDto obj = new PurchaseOrderItemDto();
                obj.setSkuId(item.getSkuId());
                obj.setQty(item.getPurchaseRequirementQty());
                items.add(obj);
            }
            if (StringUtils.isNullOrEmpty(items)) {
                continue;
            }
            order.setItems(items);
            order.setSupplierEntId(supplierId);
            reqs.add(order);
        }
        purchaseOrderService.saveAndSubmit(reqs);
    }

    @Override
    public void productionToPurchaseContract(List<PurchaseItemCreateDto> req) {
        List<ContractDto> reqs = new ArrayList<>();
        for (String supplierId : req.stream().filter(s -> StringUtils.isNullOrEmpty(s.getProviderEntId()) == false).map(s -> s.getProviderEntId()).distinct().collect(Collectors.toList())) {

            ContractDto contract = new ContractDto();
            List<ContractItemDto> items = new ArrayList<>();

            for (PurchaseItemCreateDto item : req.stream().filter(s -> supplierId.equals(s.getProviderEntId())).collect(Collectors.toList())) {
                ProductSkuVo sku = productSkuService.queryViewById(item.getSkuId());

                if (sku.getPurchaseType() != ProductPurchaseTypeEnum.Purchase) {
                    throw new BusinessException("只有外部采购商品【" + sku.getSkuCode() + "】才能生成采购订单。");
                }
                ContractItemExt contractItem = contractService.queryPurchasePrice(supplierId, item.getSkuId());
                if (contractItem == null) {
                    throw new BusinessException("没有价格协议。");
                }

                ContractItemDto obj = new ContractItemDto();
                obj.setSkuId(item.getSkuId());
                obj.setPrice(contractItem.getPrice());

                if (new BigDecimal(item.getPurchaseRequirementQty()).doubleValue() < new BigDecimal(contractItem.getBuyMinQty()).doubleValue()) {
                    obj.setQty(item.getPurchaseRequirementQty());
                }
                items.add(obj);
            }
            if (StringUtils.isNullOrEmpty(items)) {
                continue;
            }

            contract.setItems(items);
            contract.setBusinessEntId(supplierId);
            reqs.add(contract);
        }
        contractService.update(reqs);
    }

    @Override
    public void productionToBomUser(String productionOrderId, String warehouseId) {
        ProductionOrder order = baseMapper.selectById(productionOrderId);
        if (order == null) {
            throw new BusinessEntityNotFoundException(productionOrderId, "生产订单");
        }

        InventoryNoteAddDto note = new InventoryNoteAddDto();
        note.setWarehouseId(warehouseId);
        note.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        note.setRelationNoteId(productionOrderId);
        note.setRelationNoteCode(order.getCode());
        note.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION).getId());
        note.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_BOM_USER).getId());

        LambdaQueryWrapper<ProductionOrderItemBomExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItemBomExt::getOrderId, productionOrderId);
        List<ProductionOrderItemBomExt> items = productionOrderItemBomExtMapper.selectList(lq);
        List<InventoryNoteItemDto> noteItems = new ArrayList<>();
        for (ProductionOrderItemBomExt item : items) {
            if (item.getSkuItemUserQty() <= 0) {
                continue;
            }
            double totalRequirementQty = items.stream().filter(s -> s.getSkuId().equals(item.getSkuId())).mapToDouble(s -> s.getRequirementQty()).sum();
            double totalInventoryQty = items.stream().filter(s -> s.getSkuId().equals(item.getSkuId())).findFirst().get().getInventoryQty();
            if (totalInventoryQty < totalRequirementQty) {
                throw new BusinessException(String.format("【%s : %s】的库存不足，不能一次全部领完。", item.getSkuCode(), item.getNameAs()));
            }
            InventoryNoteItemDto obj = new InventoryNoteItemDto();
            obj.setSkuId(item.getSkuId());
            obj.setQty(item.getRequirementQty());
            noteItems.add(obj);
        }
        note.setItems(noteItems);
        String id = inventoryNoteService.addByOut(note);
        inventoryNoteService.submit(id);
    }

    @Override
    public void productionToBomUser(String productionOrderId, String warehouseId, String skuId, Double qty) {
        ProductionOrder order = baseMapper.selectById(productionOrderId);
        if (order == null) {
            throw new BusinessEntityNotFoundException(productionOrderId, "生产订单");
        }
        if (!order.getSubmitStatus()) {
            throw new BusinessException("生产订单没有提交。");
        }
        if (!order.getPlanWorkStatus()) {
            throw new BusinessException("生产订单还未开工。");
        }
        InventoryNoteAddDto note = new InventoryNoteAddDto();
        note.setWarehouseId(warehouseId);
        note.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        note.setRelationNoteId(productionOrderId);
        note.setRelationNoteCode(order.getCode());
        note.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION).getId());
        note.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_BOM_USER).getId());
        note.setSubmitStatus(true);

        List<InventoryNoteItemDto> items = new ArrayList<>();
        InventoryNoteItemDto item = new InventoryNoteItemDto();
        item.setSkuId(skuId);
        item.setQty(qty);
        items.add(item);
        note.setItems(items);
        inventoryNoteService.addByOut(note);
    }

    @Override
    public void productionToBomUser(ProductionOrderToBomUserDto req) {
        ProductionOrder order = queryById(req.getProductionOrderId());
        if (order == null) {
            throw new BusinessEntityNotFoundException(req.getProductionOrderId(), "生产订单");
        }
        InventoryNoteAddDto note = new InventoryNoteAddDto();
        note.setWarehouseId(req.getWarehouseId());
        note.setPersonnelId(req.getPersonnelId());
        note.setRelationNoteId(req.getProductionOrderId());
        note.setRelationNoteCode(order.getCode());
        note.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION).getId());
        note.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_BOM_USER).getId());

        note.setItems(req.getItems());
        inventoryNoteService.addByOut(note);
    }

    @Override
    public ProductionOrder queryById(String id) {
        return getBaseMapper().selectById(id);
    }

    @Override
    public IPage<ProductionOrderExt> queryBySaleOrderId(String id, Integer pageSize, Integer pageIndex) {
        IPage<ProductionOrderExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderExt::getSaleOrderId, id);
        lq.eq(ProductionOrderExt::getIsDelete, false);
        return productionOrderExtMapper.selectPage(page, lq);
    }

    @Override
    public List<ProductionOrderItem> queryItemById(String id) {
        LambdaQueryWrapper<ProductionOrderItem> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItem::getOrderId, id);
        return productionOrderItemMapper.selectList(lq);
    }

    @Override
    public IPage<ProductionOrderItemExt> queryItemById(String id, Integer pageSize, Integer pageIndex) {
        Page<ProductionOrderItemExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItemExt::getOrderId, id);
        return productionOrderItemExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionOrderItemExt> queryItem(String searchText, BooleanEnum runStatus, BooleanEnum isComplete, Integer pageSize, Integer pageIndex) {
        Page<ProductionOrderItemExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderItemExt> lq = Wrappers.lambdaQuery();
        if (runStatus != null) {
            switch (runStatus) {
                case Yes:
                    lq.eq(ProductionOrderItemExt::getPlanWorkStatus, true);
                    break;
                case No:
                    lq.eq(ProductionOrderItemExt::getPlanWorkStatus, false);
                    break;
            }
        }
        if (isComplete != null) {
            switch (isComplete) {
                case Yes:
                    lq.eq(ProductionOrderItemExt::getWorkCompleteStatus, 1);
                    break;
                case No:
                    lq.eq(ProductionOrderItemExt::getWorkCompleteStatus, 0);
                    break;
            }
        }
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionOrderItemExt::getSkuCode, searchText).or().like(ProductionOrderItemExt::getNameAs, searchText).or().like(ProductionOrderItemExt::getCode, searchText);
        }
        lq.orderByAsc(ProductionOrderItemExt::getWorkCompleteTime);
        return productionOrderItemExtMapper.selectPage(page, lq);
    }

    @Override
    public ProductionOrderItemExt queryItemByItemId(String itemId) {
        return baseMapper.selectItemByItemId(itemId);
    }

    @Override
    public IPage<ProductionOrderItemBomExt> queryItemBom(String productionOrderId, BooleanEnum lackStatus, String skuId, Integer pageSize, Integer pageIndex) {
        Page<ProductionOrderItemBomExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderItemBomExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItemBomExt::getMainSkuId, skuId);
        lq.eq(ProductionOrderItemBomExt::getOrderId, productionOrderId);
        if (lackStatus != null) {
            if (lackStatus != BooleanEnum.Default) {
                lq.eq(ProductionOrderItemBomExt::getIsAllowLackStart, lackStatus.getCode());
                lq.eq(ProductionOrderItemBomExt::getIsLack, 1);
                //lq.apply("can_user_inventory_qty < requirement_qty");
            }
        }
        lq.orderByAsc(ProductionOrderItemBomExt::getSkuCode);
        return productionOrderItemBomExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionOrderItemBomSumExt> queryItemBomSum(String searchText, String productionOrderId, Integer pageSize, Integer pageIndex) {
        Page<ProductionOrderItemBomSumExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderItemBomSumExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderItemBomSumExt::getOrderId, productionOrderId);
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionOrderItemBomSumExt::getSkuCode, searchText).or().like(ProductionOrderItemBomSumExt::getNameAs, searchText);
        }
        lq.orderByAsc(ProductionOrderItemBomSumExt::getSkuCode);
        return productionOrderItemBomSumExtMapper.selectPage(page, lq);
    }

    @Override
    public ProductionOrderVo queryViewById(String id) {
        ProductionOrderVo ret = new ProductionOrderVo();
        ProductionOrderExt obj = baseMapper.selectExtById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "生产订单");
        }
        BeanUtils.copyProperties(obj, ret);
        ret.setItems(baseMapper.selectItemById(id));
        return ret;
    }

    public ProductionOrderView queryViewByCode(String code) {
        LambdaQueryWrapper<ProductionOrderView> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderView::getCode, code);
        return productionOrderViewMapper.selectOne(lq);
    }

    @Override
    public ProductionOrderView queryViewByOrderId(String id) {
        LambdaQueryWrapper<ProductionOrderView> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderView::getOrderId, id);
        return productionOrderViewMapper.selectOne(lq);
    }

    @Override
    public IPage<ProductionOrderExt> query(String searchText, BooleanEnum runStatus, BooleanEnum isComplete, Integer pageSize, Integer pageIndex) {
        IPage<ProductionOrderExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionOrderExt::getCode, searchText).or().like(ProductionOrderExt::getSaleOrderCode, searchText);
        }
        if (runStatus != null) {
            switch (runStatus) {
                case No:
                    lq.eq(ProductionOrderExt::getPlanWorkStatus, false);
                    break;
                case Yes:
                    lq.eq(ProductionOrderExt::getPlanWorkStatus, true);
                    break;
            }
        }
        if (isComplete != null) {
            switch (isComplete) {
                case No:
                    lq.eq(ProductionOrderExt::getWorkCompleteStatus, false);
                    break;
                case Yes:
                    lq.eq(ProductionOrderExt::getWorkCompleteStatus, true);
                    break;
            }
        }
        lq.eq(ProductionOrderExt::getIsDelete, false);
        lq.orderByDesc(ProductionOrderExt::getCreateTime);
        return productionOrderExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionOrderRequirementPlanExt> queryRequirementItem(String searchText, String skudId, Integer pageSize, Integer pageIndex) {
        IPage<ProductionOrderRequirementPlanExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderRequirementPlanExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionOrderRequirementPlanExt::getNameAs, searchText).or()
                    .like(ProductionOrderRequirementPlanExt::getSkuCode, searchText).or()
                    .like(ProductionOrderRequirementPlanExt::getMainSkuCode, searchText).or()
                    .like(ProductionOrderRequirementPlanExt::getMainSkuNameAs, searchText);
        }
        if (!StringUtils.isNullOrEmpty(skudId)) {
            lq.eq(ProductionOrderRequirementPlanExt::getSkuId, skudId);
        }
        lq.eq(ProductionOrderRequirementPlanExt::getPurchaseType, ProductPurchaseTypeEnum.Purchase);
        return productionOrderRequirementPlanExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionRequirementPlanExt> queryRequirement(String searchText, String supplierEntId, Integer pageSize, Integer pageIndex) {
        Page<ProductionRequirementPlanExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionRequirementPlanExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(supplierEntId)) {
            lq.eq(ProductionRequirementPlanExt::getProviderEntId, supplierEntId);
        }
        lq.gt(ProductionRequirementPlanExt::getPurchaseRequirementQty, 0);
        lq.eq(ProductionRequirementPlanExt::getPurchaseType, ProductPurchaseTypeEnum.Purchase);
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionRequirementPlanExt::getSkuCode, searchText).or().like(ProductionRequirementPlanExt::getNameAs, searchText);
        }
        lq.orderByAsc(ProductionRequirementPlanExt::getSkuCode);
        return productionRequirementPlanExtMapper.selectPage(page, lq);
    }

    @Override
    public List<ProductionWorkOrderOutExt> queryItemBySeqSku(String productionOrderItemId) {
        LambdaQueryWrapper<ProductionWorkOrderOutExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionWorkOrderOutExt::getPurchaseSubmitStatus, false);
        if (!StringUtils.isNullOrEmpty(productionOrderItemId)) {
            lq.eq(ProductionWorkOrderOutExt::getProductionOrderItemId, productionOrderItemId);
        }
        return productionWorkOrderOutExtMapper.selectList(lq);
    }

    @Override
    public List<ProductionWorkOrderOutExt> queryItemSeqSkuByOrderId(String productionOrderId) {
        LambdaQueryWrapper<ProductionWorkOrderOutExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionWorkOrderOutExt::getPurchaseSubmitStatus, true);
        lq.eq(ProductionWorkOrderOutExt::getProductionOrderId, productionOrderId);
        return productionWorkOrderOutExtMapper.selectList(lq);
    }

    @Override
    public IPage<ProductionOrderView> queryView(String searchText, BooleanEnum runStatus, BooleanEnum isComplete, Integer pageSize, Integer pageIndex) {
        Page<ProductionOrderView> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderView> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderView::getIsDelete, false);
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionOrderView::getSkuCode, searchText.trim()).or().like(ProductionOrderView::getCode, searchText.trim()).or().like(ProductionOrderView::getSkuName, searchText.trim()).or().like(ProductionOrderView::getSaleOrderCode, searchText);
        }
        if (runStatus != null) {
            switch (runStatus) {
                case No:
                    lq.eq(ProductionOrderView::getPlanWorkStatus, false);
                    lq.orderByDesc(ProductionOrderView::getSubmitTime);
                    break;
                case Yes:
                    lq.eq(ProductionOrderView::getPlanWorkStatus, true);
                    lq.orderByDesc(ProductionOrderView::getRealWorkDate);
                    break;
            }
            //lq.orderByDesc(ProductionOrderView::getSubmitTime);
        } else {
            lq.orderByDesc(ProductionOrderView::getSubmitTime);
        }
        if (isComplete != null) {
            switch (isComplete) {
                case No:
                    lq.eq(ProductionOrderView::getProductionCompleteStatus, false);
                    break;
                case Yes:
                    lq.eq(ProductionOrderView::getProductionCompleteStatus, true);
                    //lq.orderByDesc(ProductionOrderView::getRealWorkEndTime);
                    break;
            }
        }
        //lq.orderByDesc(ProductionOrderView::getCreateTime);

        return productionOrderViewMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionOrderView> queryViewBySaleOrderId(String saleOrderId, Integer pageSize, Integer pageIndex) {
        Page<ProductionOrderView> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderView> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionOrderView::getSaleOrderId, saleOrderId);
        lq.eq(ProductionOrderView::getSubmitStatus, true);
        lq.eq(ProductionOrderView::getIsDelete, false);
        lq.orderByAsc(ProductionOrderView::getCode);
        return productionOrderViewMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionOrderView> queryViewByCanInInventory(String searchText, Integer pageSize, Integer pageIndex) {
        Page<ProductionOrderView> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionOrderView> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionOrderView::getSkuCode, searchText.trim()).or().like(ProductionOrderView::getCode, searchText.trim()).or().like(ProductionOrderView::getSkuName, searchText.trim());
        }
        lq.eq(ProductionOrderView::getPlanWorkStatus, true);
        lq.eq(ProductionOrderView::getProductionCompleteStatus, true);
        lq.eq(ProductionOrderView::getIsDelete, false);
        lq.apply(" production_qty > production_in_qty ");
        lq.orderByAsc(ProductionOrderView::getCreateTime);
        return productionOrderViewMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionCostDiffExt> queryCostMoneyDiff(String startMonth, String endMonth, Integer pageSize, Integer pageIndex) {
        Page<ProductionCostDiffExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionCostDiffExt> lq = Wrappers.lambdaQuery();
        lq.ge(ProductionCostDiffExt::getAccountMonthDesc, startMonth);
        lq.le(ProductionCostDiffExt::getAccountMonthDesc, endMonth);
        return productionCostDiffExtMapper.selectPage(page, lq);
    }
}